package com.ck.server.java8;

import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author ck
 * @date 2023/7/21 8:51
 */
@SpringBootTest
public class Stream {

    /**filter()方法接受一个谓词（一个返回boolean值的函数），并返回一个流，其中仅包含通过该谓词的元素*/
    @Test
    public void filter() {

        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        List<String> collect = names.stream().filter(item -> item.length() > 4).collect(Collectors.toList());
        System.out.println(collect);
    }

    /**map()方法可将一个流的元素转换为另一个流。它接受一个函数，该函数映射流中的每个元素到另一个元素*/
    @Test
    public void map(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> collect = numbers.stream().map(n ->
        {
            n = n * 2;
            return n;
        }).collect(Collectors.toList());
        for (Integer integer : collect) {
            System.out.println("integer = " + integer);
        }
    }


    /**sorted()方法可对流进行排序。它可以接受一个Comparator参数，也可以使用自然排序Ordering.natural()。默认排序是按升序排序*/
    @Test
    public void sorted(){
        int[] numbers = { 5, 2, 8, 3, 7 };
        int[] sortedNumbers = Arrays.stream(numbers).sorted().toArray();
        System.out.println(Arrays.toString(sortedNumbers));
    }

    /**distinct()方法从流中返回所有不同的元素。在内部，它使用equals()方法来比较元素是否相同。因此，我们需要确保equals()方法已正确实现*/
    @Test
    public void distinct(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1);
        List<Integer> collect = numbers.stream().distinct().collect(Collectors.toList());
        System.out.println(collect);
    }

    /**limit()方法可以将流限制为指定的元素数。*/
    @Test
    public void limit(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> collect = numbers.stream().limit(3).collect(Collectors.toList());
        System.out.println(collect);
    }


    /**skip()方法可跳过前N个元素。*/
    @Test
    public void skip(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> collect = numbers.stream().skip(2).collect(Collectors.toList());
        System.out.println(collect);
    }


    /**peek()方法可以用于在Stream流中获取元素同时执行一些操作，如打印、调试、观察等。通常会与其他的方法联合使用*/
    @Test
    public void peek(){
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        List<String> filteredNames = names.stream()
                .peek(System.out::println)
                .filter(name -> name.startsWith("C"))
                .peek(name -> System.out.println("Filtered value: " + name))
                .collect(Collectors.toList());
        System.out.println("-----------------------------------------------------------------");
        System.out.println(filteredNames);
    }

    /**forEach()方法可将给定的方法应用于流中的每个元素。该方法是一种消费流的方式，不会返回值*/
    @Test
    public void forEach(){
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        names.stream().forEach(System.out::println);
    }


    /** collect()方法可以将流中的元素收集到一个集合中。一般与其他方法配合使用*/
    @Test
    public void collect(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
        System.out.println(evenNumbers);
    }


    /** count()方法可以返回流中的元素数*/
    @Test
    public void count(){
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        long count = names.stream().count();
        System.out.println(count);
    }


    /**reduce()聚合方法可以将流元素聚合为单个结果。它接受一个BinaryOperator参数作为累加器*/
    @Test
    public void reduce(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
        System.out.println(sum);
    }


    /**anyMatch()方法如果至少有一个元素与给定的谓词匹配，则返回true。(任意匹配)*/
    @Test
    public void anyMatch(){
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        boolean anyStartsWithB = names.stream().anyMatch(name -> name.startsWith("B"));
        System.out.println(anyStartsWithB);
    }

    /**allMatch()方法如果所有元素都与给定谓词匹配，则返回true。(全部匹配)*/
    @Test
    public void allMatch(){
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        boolean allStartsWithB = names.stream().allMatch(name -> name.startsWith("B"));
        System.out.println(allStartsWithB);
    }


    /**noneMatch()方法，如果没有任何元素与给定谓词匹配，则返回true。(无匹配)*/
    @Test
    public void noneMatch() {
        List<String> names = Arrays.asList("Alex", "Brian", "Charles", "David");
        boolean noneStartsWithB = names.stream().noneMatch(name -> name.startsWith("E"));
        System.out.println(noneStartsWithB);
    }
}
